#include "header.h"
#include "rt.h"

static char	*shader_source_load(const char *file_name)
{
	FILE	*f;
	int		size;
	char	*src;
	int		nb_bytes;

	if ((f = fopen(file_name, "r")) == NULL)
		return ((char *)errno_msg(file_name, 0));
	fseek(f, 0, SEEK_END);
	size = ftell(f);
	rewind(f);
	src = (char *)calloc(size + 1, sizeof(*src));
	nb_bytes = fread(src, sizeof(*src), size, f);
	src[nb_bytes] = 0;
	fclose(f);
	return (src);
}

GLuint		shader_compile(const char *file_name, GLuint type)
{
	GLint	status, size;
	GLuint	shader;
	char	*src;

	if ((shader = glCreateShader(type)) == 0)
		return (error_msg("Shader", "Can't create shader", 0));
	if ((src = shader_source_load(file_name)) == NULL)
		return (0);
	glShaderSource(shader, 1, &src, 0);
	free(src);
	glCompileShader(shader);
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status != GL_TRUE)
	{
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
		src = (char *)calloc(sizeof(*src), size + 1);
		glGetShaderInfoLog(shader, size, &size, src);
		fprintf(stderr, "%s: Compilation failed: %s\n", file_name, src);
		free(src);
		getchar();
		return (0);
	}
	return (shader);
}


GLuint		shader_create(const char *file_vertex, const char *file_fragment)
{
	GLuint	vertex = 0, fragment = 0, program;
	GLint	status, size;
	char	*src;

	if (file_vertex)
		vertex = shader_compile(file_vertex, GL_VERTEX_SHADER);
	if (file_fragment)
		fragment = shader_compile(file_fragment, GL_FRAGMENT_SHADER);
	if (vertex == 0 && fragment == 0)
		return (0);

	program = glCreateProgram();
	if (vertex)
		glAttachShader(program, vertex);
	if (fragment)
		glAttachShader(program, fragment);

	glLinkProgram(program);
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status != GL_TRUE)
	{
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
		src = (char *)calloc(sizeof(*src), size + 1);
		glGetProgramInfoLog(program, size, &size, src);
		fprintf(stderr, "Program: Linking failed: %s\n", src);
		free(src);
		getchar();
		return (0);
	}
	return (program);
}

void		shader_send_3f(GLuint program, char *name, float x, float y, float z)
{
	GLuint	send;
	
	send = glGetUniformLocation(program, name);
	glUniform3f(send, x, y, z);
}